#
# Copyright (C) 2023, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use 
# under the terms of the LICENSE.md file.
#
# For inquiries contact  george.drettakis@inria.fr
#

import torch
from scene import Scene
import os
from tqdm import tqdm
from os import makedirs
from gaussian_renderer import render
import torchvision
from utils.general_utils import safe_state
from argparse import ArgumentParser
from arguments import ModelParams, PipelineParams, get_combined_args
from gaussian_renderer import GaussianModel
from utils.loss_utils import ssim
from lpipsPyTorch import lpips
from utils.image_utils import psnr
import time
import numpy as np


def render_set(model_path, name, iteration, views, gaussians, pipeline, background, save=True, psnr_only=False):
    if save:
        render_path = os.path.join(model_path, name, "ours_{}".format(iteration), "renders")
        gts_path = os.path.join(model_path, name, "ours_{}".format(iteration), "gt")
        makedirs(render_path, exist_ok=True)
        makedirs(gts_path, exist_ok=True)
    
    psnrs, ssims, lpipss = [], [], []

    t_list = []
    for idx, view in enumerate(tqdm(views, desc="Rendering progress")):
        
        torch.cuda.synchronize();t0 =time.time()
        rendered_pkg = render(view, gaussians, pipeline, background)
        torch.cuda.synchronize();t1= time.time()
        t_list.append(t1-t0)
        rendering = rendered_pkg["render"]
        gt = view.original_image[0:3, :, :].cuda()
        
        if save:
            torchvision.utils.save_image(rendering, os.path.join(render_path, '{0:05d}'.format(idx) + ".png"))
            torchvision.utils.save_image(gt, os.path.join(gts_path, '{0:05d}'.format(idx) + ".png"))
        
        rendering, gt = rendering[None, ...], gt[None, ...]
        psnrs.append(psnr(rendering, gt).item())
        if not psnr_only:
            ssims.append(ssim(rendering, gt).item())
            lpipss.append(lpips(rendering, gt, net_type='vgg').item())
        del rendering, gt, view
    
    psnr_ = sum(psnrs) / len(psnrs)
    if not psnr_only:
        ssim_ = sum(ssims) / len(ssims)
        lpips_ = sum(lpipss) / len(lpipss)
    t = np.array(t_list[5:])
    fps = 1.0 / t.mean()
    print(f'Test FPS: \033[1;35m{fps:.5f}\033[0m')
    if not psnr_only:
        print(f"\n============= PSNR={psnr_:.4f}, SSIM={ssim_:.4f}, LPIPS={lpips_:.4f} ================\n")
    else:
        print(f"\n============= PSNR={psnr_:.4f} =================\n")


def render_sets(dataset : ModelParams, iteration : int, pipeline : PipelineParams, args):
    with torch.no_grad():
        gaussians = GaussianModel(dataset, args)
        scene = Scene(dataset, gaussians, load_iteration=iteration, shuffle=False)

        bg_color = [1,1,1] if dataset.white_background else [0, 0, 0]
        background = torch.tensor(bg_color, dtype=torch.float32, device="cuda")

        # if not args.skip_train:
        #      render_set(dataset.model_path, "train", scene.loaded_iter, scene.getTrainCameras(), gaussians, pipeline, background)

        if not args.skip_test:
             render_set(dataset.model_path, "test", scene.loaded_iter, scene.getTestCameras(), gaussians, pipeline, background)

if __name__ == "__main__":
    # Set up command line argument parser
    parser = ArgumentParser(description="Testing script parameters")
    model = ModelParams(parser, sentinel=True)
    pipeline = PipelineParams(parser)
    parser.add_argument("--iteration", default=-1, type=int)
    parser.add_argument("--skip_train", action="store_true")
    parser.add_argument("--skip_test", action="store_true")
    parser.add_argument("--quiet", action="store_true")
    parser.add_argument("--gpu", type=int, default=0)    

    args = get_combined_args(parser)
    print("Rendering " + args.model_path)
    
    # Initialize system state (RNG)
    safe_state(args.quiet)
    torch.cuda.set_device(args.gpu)

    render_sets(model.extract(args), args.iteration, pipeline.extract(args), args)